package cn.sytton.taffe.framework.mybatis;

import cn.hutool.core.util.ReflectUtil;
import cn.sytton.taffe.framework.util.SecurityUtil;
import org.apache.ibatis.binding.MapperMethod;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.*;

import java.sql.Timestamp;
import java.util.Date;
import java.util.Properties;

/**
 * mybatis拦截器，自动更新4个日志字段
 *
 * @author skyrock
 */
@Intercepts({@Signature(type= Executor.class,method = "update",args = {MappedStatement.class,Object.class})})
public class SqlUpdateInterceptor implements Interceptor {

    private static final String createdUserIdFiled = "createdUserId";
    private static final String createdTimeFiled = "createdTime";
    private static final String updatedUserIdFiled = "updatedUserId";
    private static final String updatedTimeFiled = "updatedTime";

    public Object intercept(Invocation invocation) throws Throwable {
        Object[] args = invocation.getArgs();
        if (args[1] == null){
            return invocation.proceed();
        }else{
            SqlCommandType sqlCommandType = ((MappedStatement)args[0]).getSqlCommandType();
            if (SqlCommandType.INSERT.equals(sqlCommandType) || SqlCommandType.UPDATE.equals(sqlCommandType)) {
                Object field = args[1];
                if (field instanceof MapperMethod.ParamMap) {
                    // 处理mybatis-plus update(Wrapper<T> updateWrapper)方法的参数
                    if (((MapperMethod.ParamMap<?>) field).containsKey("et")) {
                        field = ((MapperMethod.ParamMap<?>) field).get("et");
                    }
                }
                if (field != null) {
                    Class<?> cls = field.getClass();
                    Timestamp now = (new Timestamp(new Date().getTime()));
                    if (SqlCommandType.INSERT.equals(sqlCommandType)) {
                        if (ReflectUtil.hasField(cls, createdUserIdFiled)) {
                            if (ReflectUtil.getFieldValue(field, createdUserIdFiled) == null) {
                                ReflectUtil.setFieldValue(field, createdUserIdFiled, SecurityUtil.getUserId());
                            }
                        }
                        if (ReflectUtil.hasField(cls, createdTimeFiled)) {
                            if (ReflectUtil.getFieldValue(field, createdTimeFiled) == null) {
                                ReflectUtil.setFieldValue(field, createdTimeFiled, now);
                            }
                        }
                    }
                    if (ReflectUtil.hasField(cls, updatedUserIdFiled)) {
                        ReflectUtil.setFieldValue(field, updatedUserIdFiled, SecurityUtil.getUserId());
                    }
                    if (ReflectUtil.hasField(cls, updatedTimeFiled)) {
                        ReflectUtil.setFieldValue(field, updatedTimeFiled, now);
                    }
                }
            }
            return invocation.proceed();
        }
    }
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }
    public void setProperties(Properties properties) { }

}
